package api;

import java.util.Map;
import org.basex.core.BaseXException;

/**
 * This class allows to manipulate with BaseX collection content.
 * Manipulates with collections which hold matches for each season and league identified by league ID
 * and also with <b>league-list</b> collection which holds info about the leagues.
 * 
 * @author Football-Statistics Team
 */
public final class CollectionManager {
    private String collection;
    private DatabaseManager dm;
    
    /**
    * Constructor
    * @param collection name of the collection (league ID)
    * @param dm DatabaseManager
    */
    public CollectionManager(String collection, DatabaseManager dm) {
        this.collection = collection;
        this.dm = dm;
    }

    /**
    * DatabaseManager setter
    * @param dm DatabaseManager
    */
    public void setDatabaseManager (DatabaseManager dm) {
        this.dm = dm;
    }

    /**
    * Collection setter
    * @param collection name of the collection (league ID)
    */    
    public void setCollection(String collection) {
        this.collection = collection;
    }

    /**
    * Gets match info from collection
    * @param id match ID
    * @throws BaseXException on database error
    * @return well-formded xml string, <b>structure:</b> <a href="http://pastebin.com/K3JUjD8S">http://pastebin.com/K3JUjD8S</a>
    */    
    public String getMatch(String id) throws BaseXException {
        String match = this.dm.queryCollection("collection('"+this.collection+"')/match[@id='"+id+"']");
        if (match.equals("")) throw new BaseXException("Match does not exist");
        return match;
    }

    /**
    * Adds match info to collection
    * @param id match ID
    * @param file well-formed xml string, <b>structure:</b> <a href="http://pastebin.com/K3JUjD8S">http://pastebin.com/K3JUjD8S</a>
    * @throws BaseXException on database error
    */     
    public void addMatch(String id, String file) throws BaseXException {
        this.dm.addXML(this.collection, id, file);
    }

    /**
    * Removes match info from collection
    * @param id match ID
    * @throws BaseXException on database error
    */     
    public void removeMatch(String id) throws BaseXException {
        this.dm.removeXML(this.collection, id);
    }

    /**
    * Updates match info in collection
    * @param id match ID
    * @param newFile well-formed XML string, <b>structure:</b> <a href="http://pastebin.com/K3JUjD8S">http://pastebin.com/K3JUjD8S</a>
    * @throws BaseXException on database error
    */     
    public void updateMatch(String id, String newFile) throws BaseXException {
        this.dm.removeXML(this.collection, id);
        this.dm.addXML(this.collection, id, newFile);
    }

    /**
    * Gets list of matches in collection
    * @return well-formed xml string, <b>structure:</b> <a href="http://pastebin.com/JKUufsS8">http://pastebin.com/JKUufsS8</a>
    * @throws BaseXException on database error
    */      
    public String getMatchList() throws BaseXException {
        return "<matches>"+this.dm.queryCollection("for $doc in collection('"+this.collection+"') return <id>{data($doc//match/@id)}</id>")+"</matches>";
    }

    /**
    * Gets list of leagues and their seasons (with league/collection IDs) (from <b>league-list</b> collection)
    * @return well-formed xml string, <b>structure:</b> <a href="http://pastebin.com/WddfRHt8">http://pastebin.com/WddfRHt8</a>
    * @throws BaseXException on database error
    */      
    public String getLeagueList() throws BaseXException {
        String query = "for $league in distinct-values(collection('league-list')//name) "
                + "let $seasons:= for $doc in collection('league-list') where data($doc//name)=$league return <season id=\"{data($doc//league/@id)}\">{data($doc//season)}</season> "
                + "order by $league "
                + "return <league><name>{$league}</name>{$seasons}</league>";
        return "<leagues>"+this.dm.queryCollection(query)+"</leagues>";
    }

    /**
    * Gets league info from <b>league-list</b> collection
    * @throws BaseXException on database error
    * @return well-formded xml string, <b>structure:</b> <a href="http://pastebin.com/e65LfbGu">http://pastebin.com/e65LfbGu</a>
    */    
    public String getLeague() throws BaseXException {
        String query = "collection('league-list')/league[@id='"+this.collection+"']";
        String league = this.dm.queryCollection(query);
        if (league.equals("")) throw new BaseXException("League does not exist");
        return league;
    }

    /**
    * Creates a new league in <b>league_list</b> collection
    * @param name league name
    * @param season league season, format: YYYY/YYYY
    * @param url url for parser, example: <a href="http://www.eurofotbal.cz/corgon-liga/2009-2010/vysledky-rozlosovani/">http://www.eurofotbal.cz/corgon-liga/2009-2010/vysledky-rozlosovani/</a>
    * @throws BaseXException on database error
    */     
    public void addLeague(String name, String season, String url) throws BaseXException {
        String xml = "<league id=\""+this.collection+"\"><name><![CDATA["+name+"]]></name><season><![CDATA["+season+"]]></season><parser-url><![CDATA["+url+"]]></parser-url></league>";
        this.dm.createCollection(this.collection);
        this.dm.addXML("league-list", this.collection, xml);
    }

    /**
    * Removes league from <b>league_list</b> collection
    * @throws BaseXException on database error
    */     
    public void removeLeague() throws BaseXException {
        this.dm.removeXML("league-list", this.collection);
        this.dm.removeCollection(this.collection);
    }

    /**
    * Updates league in <b>league_list</b> in collection
    * @param newLid new league ID
    * @param name league name
    * @param season season, format: YYYY/YYYY
    * @param url url for parser, example: <a href="http://www.eurofotbal.cz/corgon-liga/2009-2010/vysledky-rozlosovani/">http://www.eurofotbal.cz/corgon-liga/2009-2010/vysledky-rozlosovani/</a>
    * @throws BaseXException on database error
    */     
    public void updateLeague(String newLid, String name, String season, String url) throws BaseXException {
        String xml = "<league id=\""+newLid+"\"><name><![CDATA["+name+"]]></name><season><![CDATA["+season+"]]></season><parser-url><![CDATA["+url+"]]></parser-url></league>";
        this.dm.removeXML("league-list", this.collection);
        if (!this.collection.equals(newLid)) {
            this.dm.renameCollection(this.collection, newLid);
        }
        this.dm.addXML("league-list", newLid, xml);
    }
    
    /**
    * Gets parser URL for current league from <b>league-list</b> collection
    * @return URL as a String
    * @throws BaseXException on database error
    */ 
    public String getParserURL() throws BaseXException {
        return this.dm.queryCollection("collection('league-list')/league[@id='"+this.collection+"']/data(parser-url)");
    }

    /**
    * Checks if a match exists in current league/collection
    * @param mid match ID
    * @return True if the match exists, False otherwise
    * @throws BaseXException on database error
    */     
    public boolean matchExists(String mid) throws BaseXException {
        return !this.dm.queryCollection("collection('"+this.collection+"')/match[@id='"+mid+"']/@id").equals("");
    }

    /**
    * Filters out new matches URLs (for the parser)
    * @param mids Map with <b>all</b> detected matches IDs in current league
    * @return well-formed xml-string with new matches, <b>structure:</b> <a href="http://pastebin.com/XAqgr0aN">http://pastebin.com/XAqgr0aN</a>
    * @throws BaseXException on database error
    */     
    public String getNewMatches(Map<String, String> mids) throws BaseXException {
        String xml = "";
        for (String id : mids.keySet()) {
            if (!matchExists(id)) {
                xml += "<id url=\""+mids.get(id)+"\">"+id+"</id>";
            }
        }
        if (!xml.equals("")) {
            xml = "<matches>"+xml+"</matches>";
        }
        return xml;
    }

    /**
    * Gets list of teams in collection
    * @return well-formed xml string, <b>structure:</b> <a href="http://pastebin.com/nECLFs82">http://pastebin.com/nECLFs82</a>
    * @throws BaseXException on database error
    */      
    public String getTeamList() throws BaseXException {
        return "<teams>"+this.dm.queryCollection("for $team in distinct-values(collection('"+this.collection+"')//match/home) return <team>{$team}</team>")+"</teams>";
    }
}
